﻿//
//                       _oo0oo_
//                      o8888888o
//                      88" . "88
//                      (| -_- |)
//                      0\  =  /0
//                    ___/`---'\___
//                  .' \\|     |// '.
//                 / \\|||  :  |||// \
//                / _||||| -:- |||||- \
//               |   | \\\  -  /// |   |
//               | \_|  ''\---/''  |_/ |
//               \  .-\__  '-'  ___/-. /
//             ___'. .'  /--.--\  `. .'___
//          ."" '<  `.___\_<|>_/___.' >' "".
//         | | :  `- \`.;`\ _ /`;.`/ - ` : | |
//         \  \ `_.   \_ __\ /__ _/   .-` /  /
//     =====`-.____`.___ \_____/___.-`___.-'=====
//                       `=---='
//
//
//     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//               佛祖保佑         永无BUG
//
//     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#region << 版 本 注 释 >>

/*----------------------------------------------------------------
* 类 名 称 ：EventSystem
* 类 描 述 ：
* 作    者 ：henrychang
* 创建时间 ：2019/1/7 16:09:47
*******************************************************************
* Copyright @ henrychang 2018. All rights reserved.
*******************************************************************
//----------------------------------------------------------------*/

#endregion << 版 本 注 释 >>

using System.Collections.Generic;
using TouchFish.ObjectPool;
using TouchFish.SingletonClass;
using UnityEngine;

namespace TouchFish.Event
{
    #region 事件接口

    public delegate void OnEvent(int key, params object[] param);

    #endregion 事件接口

    public interface IMessageSystem
    {
        bool RegisterMessage(int key, OnEvent fun);

        void UnRegisterMessage(int key, OnEvent fun);

        void UnRegisterMessage(int key);

        bool SendMessage(int key, params object[] param);
    }

    public class MessageSystem : IPoolable, IMessageSystem
    {
        private readonly Dictionary<int, ListenerWrap> mAllListenerMap = new Dictionary<int, ListenerWrap>(50);

        public bool IsRecycled { get; set; }

        #region 内部结构

        private class ListenerWrap
        {
            private LinkedList<OnEvent> mEventList;

            public bool Fire(int key, params object[] param)
            {
                if (mEventList == null)
                {
                    return false;
                }

                var next = mEventList.First;
                OnEvent call = null;
                LinkedListNode<OnEvent> nextCache = null;

                while (next != null)
                {
                    call = next.Value;
                    nextCache = next.Next;
                    call(key, param);

                    next = next.Next ?? nextCache;
                }

                return true;
            }

            public bool Add(OnEvent listener)
            {
                if (mEventList == null)
                {
                    mEventList = new LinkedList<OnEvent>();
                }

                if (mEventList.Contains(listener))
                {
                    return false;
                }

                mEventList.AddLast(listener);
                return true;
            }

            public void Remove(OnEvent listener)
            {
                if (mEventList == null)
                {
                    return;
                }

                mEventList.Remove(listener);
            }

            public void RemoveAll()
            {
                if (mEventList == null)
                {
                    return;
                }

                mEventList.Clear();
            }
        }

        #endregion 内部结构

        public bool RegisterMessage(int key, OnEvent fun)
        {
            ListenerWrap wrap;
            if (!mAllListenerMap.TryGetValue(key, out wrap))
            {
                wrap = new ListenerWrap();
                mAllListenerMap.Add(key, wrap);
            }

            if (wrap.Add(fun))
            {
                return true;
            }

            Debug.Log("Already Register Same Event:" + key);
            return false;
        }

        public void UnRegisterMessage(int key, OnEvent fun)
        {
            ListenerWrap wrap;
            if (mAllListenerMap.TryGetValue(key, out wrap))
            {
                wrap.Remove(fun);
            }
        }

        public void UnRegisterMessage(int key)
        {
            ListenerWrap wrap;
            if (mAllListenerMap.TryGetValue(key, out wrap))
            {
                wrap.RemoveAll();
                wrap = null;

                mAllListenerMap.Remove(key);
            }
        }

        public bool SendMessage(int key, params object[] param)
        {
            ListenerWrap wrap;
            if (mAllListenerMap.TryGetValue(key, out wrap))
            {
                return wrap.Fire(key, param);
            }
            return false;
        }

        public void OnRecycled()
        {
            mAllListenerMap.Clear();
        }
    }

    public class MessageDispatcher : Singleton<MessageDispatcher>, ISingleton
    {
        /// <summary>
        /// common event manager
        /// </summary>
        private MessageSystem _commonMessageSystem = new MessageSystem();

        public void OnSingletonInit()
        {
            _commonMessageSystem = new MessageSystem();
        }

        public MessageSystem CommonMessageManager
        {
            get { return this._commonMessageSystem; }
            private set { }
        }
    }
}